package process;

import java.util.ArrayList;

import common.Pair;

public class Defuzzification {
	private ArrayList<Pair<Double, Double>> points = new ArrayList<Pair<Double, Double>>();
	private int number = 100;
	/**
	 * <point x="0.0" y="0.0"/>
	 * <point x="0.05" y="0.02"/>
	 * <point x="0.1" y="0.05"/>
	 * <point x="0.15" y="0.12"/>
	 * <point x="0.2" y="0.2"/>
	 * <point x="0.3" y="0.8"/>
	 * <point x="0.4" y="0.95"/>
	 * <point x="0.45" y="0.98"/>
	 * <point x="0.5" y="1.0"/>
	 * <point x="0.55" y="0.98"/>
	 * <point x="0.6" y="0.95"/>
	 * <point x="0.7" y="0.8"/>
	 * <point x="0.8" y="0.2"/>
	 * <point x="0.85" y="0.12"/>
	 * <point x="0.9" y="0.05"/>
	 * <point x="0.95" y="0.02"/>
	 * <point x="1.0" y="0.0"/>
	 */
	public Defuzzification(){
		points.add( new Pair<Double, Double>( 0.0 ,0.0 ) );
		points.add( new Pair<Double, Double>( 0.5 ,0.02 ) );
		points.add( new Pair<Double, Double>( 1.0 ,0.05 ) );
		points.add( new Pair<Double, Double>( 1.5 ,0.12 ) );
		points.add( new Pair<Double, Double>( 2.0 ,0.2 ) );
		points.add( new Pair<Double, Double>( 3.0 ,0.8 ) );
		points.add( new Pair<Double, Double>( 4.0 ,0.95 ) );
		points.add( new Pair<Double, Double>( 4.5 ,0.98 ) );
		points.add( new Pair<Double, Double>( 5.0 ,1.0 ) );
		points.add( new Pair<Double, Double>( 6.0 ,0.95 ) );
		points.add( new Pair<Double, Double>( 7.0 ,0.8 ) );
		points.add( new Pair<Double, Double>( 8.0 ,0.2 ) );
		points.add( new Pair<Double, Double>( 8.5 , 0.12 ) );
		points.add( new Pair<Double, Double>( 9.0 ,0.05 ) );
		points.add( new Pair<Double, Double>( 9.5 ,0.02 ) );
		points.add( new Pair<Double, Double>( 10.0 ,0.0 ) );
	}
	
	public double defuzzy( double max ){
		double sumTop = 0;
		double sumBottom = 0;
		int maxX = 10;
		double step = (double)maxX / number;
		for( int i=0 ; i<number; i++ ){
			double x =  i * step;
			double value = getFuzzyValue( 0 + x);
			sumBottom += value;
			if( value > max ){
				sumTop += x * max;
			}else{
				sumTop += x *value;
			}
		}
		return sumTop / sumBottom;
	}
	
	private double getFuzzyValue( double x ) {
		int leftIndex = 0;
		int rightIndex = 0;
		for( int i = 0; i<points.size() ; i++ ){
			Pair<Double, Double> point = points.get(i);
				
			if( x < point.first ){
				rightIndex = i;			
				break;
			}else{
				leftIndex = i;
			}
		}
		if( rightIndex> leftIndex ){
			double leftX = points.get( leftIndex).first;
			double rightX = points.get( rightIndex ).first;
			double height = points.get( leftIndex).second > points.get( rightIndex ).second ?   
					points.get( leftIndex).second - points.get( rightIndex ).second :
						points.get( rightIndex ).second - points.get( leftIndex).second;
			return height / ( rightX - leftX ) * (x-leftX);
		}else if( leftIndex == points.size()-1 ){
			return points.get( leftIndex ).second;
		}else if( rightIndex == 0 ){
			return points.get( rightIndex ).second;
		}
		return 0;
	}
}
